package com.small.common.util.jwt;

import com.small.common.util.Encoding;
import com.small.common.util.jwt.constant.MsgAuth;
import com.small.common.util.jwt.info.IJwtInfo;
import com.small.common.base.BaseConstants;
import com.small.common.util.encrypt.RSAHelper;
import com.small.common.util.jwt.info.impl.JwtInfoImpl;
import io.jsonwebtoken.*;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;

import java.net.URLEncoder;

/**
 * 作者: fenny
 * 邮箱: 893146555@qq.com
 * 时间: 2017/10/15 15:31
 * 描述: JWT获取基本信息|生成token
 */
public class JwtHelper {

    /**
     * @param jwtInfo    基本信息
     * @param priKeyPath 私钥
     * @param expire     过期时间[秒]
     * @return 密钥加密后的token
     * @throws Exception e
     */
    public static String generateToken(IJwtInfo jwtInfo, String priKeyPath, int expire) throws Exception {
        return Jwts.builder()
                .setSubject(jwtInfo.getAccount())
                .claim(BaseConstants.KEY_ID, jwtInfo.getId())
                .claim(BaseConstants.KEY_NAME, StringUtils.isNotEmpty(jwtInfo.getName()) ? URLEncoder.encode(jwtInfo.getName(), Encoding.UTF8) : "")
                .claim(BaseConstants.KEY_ROLES, jwtInfo.getRoles())
                .claim(BaseConstants.KEY_IS_SYSTEM, jwtInfo.getIsSystem())
                .claim(BaseConstants.KEY_DATA, StringUtils.isNotEmpty(jwtInfo.getData()) ? URLEncoder.encode(jwtInfo.getData(), Encoding.UTF8) : "")
                .setExpiration(DateTime.now().plusSeconds(expire).toDate())
                .signWith(SignatureAlgorithm.RS256, RSAHelper.getInstance().getPrivateKey(priKeyPath))
                .compact();
    }

    /**
     * @param token      token
     * @param pubPathKey 公钥
     * @return 获取token中的用户信息
     * @throws Exception e
     */
    public static IJwtInfo getTokenInfo(String token, String pubPathKey) throws Exception {
        try {
            Jws<Claims> claimsJws = parserToken(token, pubPathKey);
            Claims body = claimsJws.getBody();
            JwtInfoImpl jwtInfo = new JwtInfoImpl();
            jwtInfo.setAccount(body.getSubject());
            jwtInfo.setId(body.get(BaseConstants.KEY_ID, Long.class));
            jwtInfo.setName(body.get(BaseConstants.KEY_NAME, String.class));
            jwtInfo.setRoles(body.get(BaseConstants.KEY_ROLES, String.class));
            jwtInfo.setData(body.get(BaseConstants.KEY_DATA, String.class));
            jwtInfo.setIsSystem(body.get(BaseConstants.KEY_IS_SYSTEM, Integer.class));
            jwtInfo.setToken(token);
            return jwtInfo;
        } catch (ExpiredJwtException ex) {
            throw MsgAuth.JWT_TOKEN_EXPIRED_EXCEPTION;
        } catch (SignatureException ex) {
            throw MsgAuth.JWT_SIGNATURE_EXCEPTION;
        } catch (IllegalArgumentException ex) {
            throw MsgAuth.JWT_ILLEGAL_ARGUMENT_EXCEPTION;
        }
    }

    /**
     * @param token      token
     * @param pubPathKey 公钥
     * @return 公钥解析后的token
     * @throws Exception e
     */
    private static Jws<Claims> parserToken(String token, String pubPathKey) throws Exception {
        return Jwts.parser().setSigningKey(RSAHelper.getInstance().getPublicKey(pubPathKey)).parseClaimsJws(token);
    }

}
